package com.xd.common.smsLogin;

import com.xd.common.exception.XkdException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class MobilecodeAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    private static final String loginCodeError = "loginCodeError:";

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        MobilecodeAuthenticationToken mobilecodeAuthenticationToken = (MobilecodeAuthenticationToken) authentication;
        String phone = mobilecodeAuthenticationToken.getPhone();
        String mobileCode = mobilecodeAuthenticationToken.getMobileCode();

        // 从redis中读取手机号对应的验证码及其用户名
        String code = (String) redisTemplate.opsForValue().get("loginCode:"+phone);
        // 判断验证码是否一致

        if (StringUtils.isEmpty(code)){
            throw new XkdException("验证码失效");
        }
        if (!mobileCode.equals(code)) {
            //判断验证码如果5分钟内错误5次则删除验证码
            Integer errorCount = (Integer) redisTemplate.opsForValue().get(loginCodeError+phone);
            if (errorCount == null){
                redisTemplate.opsForValue().set(loginCodeError+phone,1,5, TimeUnit.MINUTES);
            }else {
                if (errorCount >= 5){
                    redisTemplate.delete("loginCode:"+phone);
                    redisTemplate.delete(loginCodeError+phone);
                }else {
                    redisTemplate.opsForValue().increment(loginCodeError+phone,1);
                }
            }
            throw new XkdException("验证码错误");
        }

        // 如果验证码一致，从数据库中读取该手机号对应的用户信息
        UserDetails loadedUser = userDetailsService.loadUserByUsername(phone);
        if (loadedUser == null) {
            throw new UsernameNotFoundException("用户不存在");
        } else {
            return new MobilecodeAuthenticationToken(loadedUser, null, loadedUser.getAuthorities());
        }
    }


    @Override
    public boolean supports(Class<?> aClass) {
        return MobilecodeAuthenticationToken.class.isAssignableFrom(aClass);
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
}